package android.demo.timer;

import android.os.Handler;
import android.os.Looper;

/**
 * 我们知道，在android下，使用timer是不能直接在task里更新ui的，
 * 必须发送消息到ui线程， 然后在ui线程接收消息进行处理。
 * 所以我封装了一个可以在直接更新ui线程的timer类，使用起来方便些。
 * 
 * <pre>
 * 使用示例：
 * 首先创建对象
        HandleTimer mTimer = new HandleTimer() {
            
            protected void onTime() {
                // 在这里做更新ui的操作
                setTitle("" + System.currentTimeMillis());
            }
        };
 * 然后调用相关方法
 * mTimer.start(period);          // 直接启动timer，参数为定时控制的间隔时间
 * mTimer.start(delay, period);   // 延迟启动timer
 * mTimer.restart(period);        // 重新启动timer
 * mTimer.restart(delay, period); // 重新启动timer
 * mTimer.stop();                 // 停止timer
 * </pre>
 * @author guojiandong
 */
public abstract class HandleTimer {

	private Handler mHandler = new Handler(Looper.getMainLooper());
    private Runnable mRunnable;

    /**
     * Create a new HandleTimer for update UI thread.
     */
    public HandleTimer() {}

    /**
     * Start timer. <br>
     * If timer has been started, stop first. <br>
     * 
     * @param period period time
     */
    public synchronized void restart(final long period) {
        restart(0, period);
    }

    /**
     * Start timer. <br>
     * If timer has been started, stop first. <br>
     * 
     * @param delay delay time
     * @param period period time
     */
    public synchronized void restart(long delay, final long period) {
        stop();
        start(delay, period);
    }

    /**
     * Start timer. <br>
     * If timer has been started, do nothing.
     * 
     * @param period period time
     */
    public synchronized void start(final long period) {
        start(0, period);
    }

    /**
     * Start timer. <br>
     * If timer has been started, do nothing.
     * 
     * @param delay delay time
     * @param period period time
     */
    public synchronized void start(long delay, final long period) {
        if (mRunnable != null) {
            return;
        }
        mRunnable = new Runnable() {
            public void run() {
                onTime();
                mHandler.postDelayed(this, period);
            }
        };
        mHandler.postDelayed(mRunnable, delay);
    }

    /**
     * Stop timer.
     */
    public synchronized void stop() {
        if (mRunnable != null) {
            mHandler.removeCallbacks(mRunnable);
            mRunnable = null;
        }
    }

    /**
     * Call back function on time.
     */
    protected abstract void onTime();

}
